/*****************************************************************************
 * Qwt Examples - Copyright (C) 2002 Uwe Rathmann
 * This file may be used under the terms of the 3-clause BSD License
 *****************************************************************************/

#include "Plot.h"

#include <QwtPlotGrid>
#include <QwtPlotItem>
#include <QwtScaleMap>
#include <QwtPlotLayout>
#include <QwtInterval>
#include <QwtPainter>
#include <QwtMath>

#include <QPainter>

class TextItem : public QwtPlotItem
{
public:
    void setText(const QString& text)
    {
        m_text = text;
    }

    virtual void draw(QPainter* painter, const QwtScaleMap&, const QwtScaleMap&, const QRectF& canvasRect) const QWT_OVERRIDE
    {
        const int margin      = 5;
        const QRectF textRect = canvasRect.adjusted(margin, margin, -margin, -margin);

        painter->setPen(Qt::white);
        painter->drawText(textRect, Qt::AlignBottom | Qt::AlignRight, m_text);
    }

private:
    QString m_text;
};

// RectItem shows how to implement a simple plot item,
// what wouldn't be necessary as QwtPlotShapeItem
// would do the same

class RectItem : public QwtPlotItem
{
public:
    enum Type
    {
        Rect,
        Ellipse
    };

    explicit RectItem(Type type) : m_type(type)
    {
    }

    void setPen(const QPen& pen)
    {
        if (pen != m_pen) {
            m_pen = pen;
            itemChanged();
        }
    }

    void setBrush(const QBrush& brush)
    {
        if (brush != m_brush) {
            m_brush = brush;
            itemChanged();
        }
    }
    void setRect(const QRectF& rect)
    {
        if (m_rect != rect) {
            m_rect = rect;
            itemChanged();
        }
    }

    virtual QRectF boundingRect() const QWT_OVERRIDE
    {
        return m_rect;
    }

    virtual void draw(QPainter* painter, const QwtScaleMap& xMap, const QwtScaleMap& yMap, const QRectF&) const QWT_OVERRIDE
    {
        if (m_rect.isValid()) {
            const QRectF rect = QwtScaleMap::transform(xMap, yMap, m_rect);

            painter->setPen(m_pen);
            painter->setBrush(m_brush);

            if (m_type == Ellipse)
                QwtPainter::drawEllipse(painter, rect);
            else
                QwtPainter::drawRect(painter, rect);
        }
    }

private:
    QPen m_pen;
    QBrush m_brush;
    QRectF m_rect;
    Type m_type;
};

Plot::Plot(QWidget* parent, const QwtInterval& interval) : QwtPlot(parent)
{
    for (int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++)
        setAxisScale(axisPos, interval.minValue(), interval.maxValue());

    setCanvasBackground(QColor(Qt::darkBlue));
    plotLayout()->setAlignCanvasToScales(true);

    // grid
    QwtPlotGrid* grid = new QwtPlotGrid;
    // grid->enableXMin(true);
    grid->setMajorPen(Qt::white, 0, Qt::DotLine);
    grid->setMinorPen(Qt::gray, 0, Qt::DotLine);
    grid->attach(this);

    const int numEllipses = 10;

    for (int i = 0; i < numEllipses; i++) {
        const double x = interval.minValue() + qwtRand() % qRound(interval.width());
        const double y = interval.minValue() + qwtRand() % qRound(interval.width());
        const double r = interval.minValue() + qwtRand() % qRound(interval.width() / 6);

        const QRectF area(x - r, y - r, 2 * r, 2 * r);

        RectItem* item = new RectItem(RectItem::Ellipse);
        item->setRenderHint(QwtPlotItem::RenderAntialiased, true);
        item->setRect(area);
        item->setPen(QPen(Qt::yellow));
        item->attach(this);
    }

    TextItem* textItem = new TextItem();
    textItem->setText("Navigation Example");
    textItem->attach(this);

    m_rectItem = new RectItem(RectItem::Rect);
    m_rectItem->setPen(Qt::NoPen);
    QColor c = Qt::gray;
    c.setAlpha(100);
    m_rectItem->setBrush(QBrush(c));
    m_rectItem->attach(this);
}

void Plot::updateLayout()
{
    QwtPlot::updateLayout();

    const QwtScaleMap xMap = canvasMap(QwtAxis::XBottom);
    const QwtScaleMap yMap = canvasMap(QwtAxis::YLeft);

    const QRect cr  = canvas()->contentsRect();
    const double x1 = xMap.invTransform(cr.left());
    const double x2 = xMap.invTransform(cr.right());
    const double y1 = yMap.invTransform(cr.bottom());
    const double y2 = yMap.invTransform(cr.top());

    const double xRatio = (x2 - x1) / cr.width();
    const double yRatio = (y2 - y1) / cr.height();

    Q_EMIT resized(xRatio, yRatio);
}

void Plot::setRectOfInterest(const QRectF& rect)
{
    m_rectItem->setRect(rect);
}
